using Cinemachine;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using Lean.Touch;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 自由视角相机控制器
    /// </summary>
    public abstract class FreeViewCameraController : TCameraController
    {
        /// <summary>
        /// 操作相机缩放的速度
        /// </summary>
        protected const float VcamScaleFactor = 1;
        protected const float MinCameraDistance = 1.5f;
        protected const float MaxCameraDistance = 10;
        protected const float DefaultCameraVerticalAngle = 20;
        protected const float ReverseAngleDuration = 2;

        protected CinemachinePOV _vcCharCameraPov;
        protected CinemachineFramingTransposer _vcCharCameraBody;

        /// <summary>
        /// 跟随主角的视角相机
        /// </summary>
        protected override CinemachineVirtualCamera vcCharCamera => vc_Character;
        protected override CinemachinePOV vcCharCameraPov => _vcCharCameraPov;
        protected override CinemachineFramingTransposer vcCharCameraBody => _vcCharCameraBody;
        /// <summary>
        /// 玩家是否正在移动
        /// </summary>
        /// <returns></returns>
        protected abstract bool isPlayerMoving { get; }

        protected override UniTask PreloadCamera()
        {
            var cameraRoot = GameObject.Find("CameraRoot");
            if (cameraRoot == null)
            {
                LogGame.LogError("Can't find CameraRoot.");
                return UniTask.CompletedTask;
            }
            cameraRootBinding = cameraRoot.GetComponent<ObjectBinding>();

            InitBinding(cameraRootBinding);

            //获取原生角色相机
            _vcCharCameraPov = vc_Character.GetCinemachineComponent<CinemachinePOV>();
            _vcCharCameraBody = vc_Character.GetCinemachineComponent<CinemachineFramingTransposer>();

            //相机碰撞器，处理山体类碰撞
            var cameraCollider = vc_Character.gameObject.AddComponent<CinemachineCollider>();
            cameraCollider.m_MinimumDistanceFromTarget = 1f;        // 相机与主角最小距离，太小就会和主角穿模
            cameraCollider.m_DistanceLimit = 3f;                    // 相机到主角之间的射线检测最大距离
            cameraCollider.m_Strategy = CinemachineCollider.ResolutionStrategy.PullCameraForward;

            //动画相机
            vcMoveTargetPov = vc_MoveTarget.GetCinemachineComponent<CinemachinePOV>();
            vcMoveTargetBody = vc_MoveTarget.GetCinemachineComponent<CinemachineFramingTransposer>();

            //根据配置设置默认值
            _defaultCameraCharacterDistance = _vcCharCameraBody.m_CameraDistance;
            _defaultCameraCharacterRotate = new Vector2(_vcCharCameraPov.m_VerticalAxis.Value, _vcCharCameraPov.m_HorizontalAxis.Value);
            _defaultCameraCharRotateMinMax = new Vector2(_vcCharCameraPov.m_HorizontalAxis.m_MinValue, _vcCharCameraPov.m_HorizontalAxis.m_MaxValue);

            _fixCameraCharacterDistance = _defaultCameraCharacterDistance;
            _fixCameraCharacterRotate = _defaultCameraCharacterRotate;
            _fixCameraCharRotateMinMax = _defaultCameraCharRotateMinMax;

            vcCharCameraBody.m_CameraDistance = _fixCameraCharacterDistance;
            SetPOV(vcCharCameraPov, _fixCameraCharacterRotate, _fixCameraCharRotateMinMax);

            return UniTask.CompletedTask;
        }

        protected override bool OnTryPinchScaleCamera(List<LeanFinger> fingers)
        {
            var pinchScale = LeanGesture.GetPinchScale(fingers);
            if (pinchScale != 1) //缩放
            {
                TrySwitchCameraToManual();
                float delta = pinchScale - 1;
                var distance = Mathf.Clamp(_vcCharCameraBody.m_CameraDistance - delta * VcamScaleFactor,
                MinCameraDistance, MaxCameraDistance);
                _vcCharCameraBody.m_CameraDistance = distance;
                return true;
            }
            return false;
        }

        protected override void RotateCamera(Vector2 delta)
        {
            _vcCharCameraPov.m_HorizontalAxis.Value += delta.x * VcamRotateFactor;
            _vcCharCameraPov.m_VerticalAxis.Value += delta.y * VcamRotateFactor * -1;
        }

        protected override void OnUpdate(float deltaTime)
        {
            base.OnUpdate(deltaTime);

            //处理移动时相机倾角回正的逻辑
            if (cameraState == CameraStateType.FollowCharacter && isPlayerMoving)
            {
                var curValue = _vcCharCameraPov.m_VerticalAxis.Value;
                _vcCharCameraPov.m_VerticalAxis.Value = Mathf.Lerp(curValue, DefaultCameraVerticalAngle, deltaTime / ReverseAngleDuration);
            }
        }
    }
}
